package com.jacky.support;

import com.jacky.annotation.OpenApi;
import com.jacky.entity.Response;
import org.springframework.core.MethodParameter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.stereotype.Component;
import org.springframework.ui.Model;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.List;
import java.util.Map;

/**
 * Created by jacky on 2018/1/16.
 */
public class OpenApiReturnValueHandler implements HandlerMethodReturnValueHandler {

    private final HandlerMethodReturnValueHandler delegate;

    public OpenApiReturnValueHandler(HandlerMethodReturnValueHandler delegate) {
        this.delegate = delegate;
    }

    /**
     * 判断方法上的注解是不是OpanApi
     * @param methodParameter
     * @return
     */
    @Override
    public boolean supportsReturnType(MethodParameter methodParameter) {
       return methodParameter.getMethodAnnotation(OpenApi.class) != null || methodParameter.getMethodAnnotation(ResponseBody.class) != null;
    }

    @Override
    public void handleReturnValue(Object returnValue,
                                  MethodParameter returnType,
                                  ModelAndViewContainer mavContainer,
                                  NativeWebRequest webRequest) throws Exception {
        Object newValue = returnValue;
        Class<?> returnParaType = returnType.getParameterType(); //获得返回值类型
        if (!void.class.isAssignableFrom(returnParaType)) {
            // 不是Response、Map、Model等类型的返回值，需要包裹为Response类型
            if (!Response.class.isAssignableFrom(returnParaType) && !Map.class.isAssignableFrom(returnParaType)
                    && !Model.class.isAssignableFrom(returnParaType) && returnType.getMethodAnnotation(OpenApi.class) != null) {
                newValue = new Response<Object>(returnValue);     //包装一层
            }else {
                newValue = returnValue;                           //不包装
            }
            delegate.handleReturnValue(newValue, returnType, mavContainer, webRequest);
        }
    }
}
